package com.fz.aop.log;

import com.fz.entity.log.ClientErrorLog;
import com.fz.entity.member.Member;
import com.fz.mapper.log.ClientErrorLogMapper;
import com.fz.security.utils.SecurityUtils;
import com.fz.utils.IpUtils;
import com.fz.utils.JacksonUtils;
import com.fz.utils.StringUtils;
import com.fz.utils.ThrowableUtil;
import io.swagger.annotations.ApiOperation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

//client系统异常日志
@Component
@Aspect
@SuppressWarnings("unchecked")
public class UserErrorLogAspect  {

    @Resource
    private ClientErrorLogMapper appErrorLogMapper;

    ThreadLocal<Long> startTime = new ThreadLocal<>();
    /**
     * 定义切点 所有的接口
     */
    @Pointcut(" execution(* com.fz.controller..*(..))")
    public void errorPointCut() {

    }

    @Before("errorPointCut()")
    public void doBefore() throws Throwable {
        startTime.set(System.currentTimeMillis());
    }


    @AfterThrowing(pointcut = "errorPointCut()", throwing = "e")
    public void afterThrow(JoinPoint joinPoint, Exception e) {
        //计算接口耗时
        Long time = System.currentTimeMillis() - startTime.get();
        //获取request
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        //获取异常信息
        String errorDetail = ThrowableUtil.stackTraceToString(e.getClass().getName(), e.getMessage(), e.getStackTrace());
        //保存异常日志
        saveErrorLog(joinPoint,request,time,errorDetail);
    }


    /**
     * @方法描述: 插入异常日志
     * @参数:
     * @返回值:
     * @创建人: I am God
     * @创建时间:: 2021/3/1
     */
    public void saveErrorLog(JoinPoint joinPoint, HttpServletRequest request, Long time, String errorDetail ){
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        //获取方法路径
        String methodName = joinPoint.getTarget().getClass().getName()+"."+signature.getName()+"()";
        //获取整体参数
        String params = "";
        //参数值
        Object[] argValues = joinPoint.getArgs();
        //参数名称
        String[] argNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames();
        if(argValues != null){
            for (int i = 0; i < argValues.length; i++) {
                if(StringUtils.checkRes(argNames[i])){
                    params = params + " "+ argNames[i] + ": " + JacksonUtils.obj2String(argValues[i]) + ",";
                }
            }
        }
        //获取ApiOperation的值 -- 接口描述
        ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
        String apiOperationValue = apiOperation.value();
        //获取登录的用户名
        Member userVo = SecurityUtils.getCurrentUser();
        String loginid = "" ;
        if(userVo != null){
            loginid = userVo.getUid().toString();
        }
        //获取请求ip
        String requestIp = IpUtils.getIpAddr(request);
        //获取ip所属地
        String ipAddress = IpUtils.getCityInfo(requestIp);
        //获取浏览器
        String browser = IpUtils.getBrowser(request);

        ClientErrorLog clientErrorLog = new ClientErrorLog();
        clientErrorLog.setUid(loginid);
        if(StringUtils.isNotEmpty(params)){
            params = params.substring(0,params.length() - 1);
        }
        clientErrorLog.setParam("{ "+params + " }");
        clientErrorLog.setMethod(methodName);
        clientErrorLog.setDescription(apiOperationValue);
        clientErrorLog.setRequestIp(requestIp);
        clientErrorLog.setTime(time.toString());
        clientErrorLog.setIpAddress(ipAddress);
        clientErrorLog.setBrowser(browser);
        clientErrorLog.setErrorDetail(errorDetail);
        appErrorLogMapper.insert(clientErrorLog);
    }



}
